mod proxy;

use std::sync::{atomic::AtomicBool, Arc};

use signal_hook::consts::TERM_SIGNALS;
use signal_hook::flag;
// A friend of the Signals iterator, but can be customized by what we want yielded about each
// signal.
use signal_hook::iterator::exfiltrator::WithOrigin;
use signal_hook::iterator::SignalsInfo;

pub fn serv() -> Result<(), Box<dyn std::error::Error>> {
    // Initialize log
    // TODO configuration file loading now depends on the workspace folder, will consider later.
    log4rs::init_file("conf/log4rs.yaml", Default::default())?;

    // Make sure double CTRL+C and similar kills
    let term_now = Arc::new(AtomicBool::new(false));
    for sig in TERM_SIGNALS {
        // When terminated by a second term signal, exit with exit code 1.
        // This will do nothing the first time (because term_now is false).
        flag::register_conditional_shutdown(*sig, 1, Arc::clone(&term_now))?;
        // But this will "arm" the above for the second time, by setting it to true.
        // The order of registering these is important, if you put this one first, it will
        // first arm and then terminate ‒ all in the first round.
        flag::register(*sig, Arc::clone(&term_now))?;
    }

    // Subscribe to all these signals with information about where they come from. We use the
    // extra info only for logging in this example (it is not available on all the OSes or at
    // all the occasions anyway, it may return `Unknown`).
    let mut sigs = vec![];
    sigs.extend(TERM_SIGNALS);
    let mut signals = SignalsInfo::<WithOrigin>::new(&sigs)?;

    let server = proxy::http::serv();

    for info in &mut signals {
        // Will print info about signal + where it comes from.
        log::info!("Received a signal {:?}", info);
        match info.signal {
            // Other signals are not handle here.
            // only handle term signals
            _ => {
                // These are all the ones left
                log::info!("Shuting down server.");
                break;
            }
        }
    }
    drop(server);
    Ok(())
}
